/*
 *  GEPoint3d.h
 *  TestGE
 *
 *  Created by Quoc Dung Chu on 15/07/11.
 *  Copyright 2011 Paris 6. All rights reserved.
 *
 */

#ifndef GE_POINT_3D_H
#define GE_POINT_3D_H

#include "GELine3d.h"
#include "GETuple3d.h"
#include "GEVector3d.h"


namespace game_engine
{
	namespace vect_math
	{
		template <class T> class GELine3d;
		
		template <class T>
		class GEPoint3d : public GETuple3d<T> {
			
		public:
			
			
			
			GEPoint3d (T x, T y, T z):GETuple3d<T>(x,y,z) {}
			
			T distance( const GEPoint3d<T>& other) const
			{
				return (GEVector3d<T>(this->X - other.X, this->Y - other.Y, this->Z - other.Z)).length();
			}
			
			
			
			//bool isBetweenPoints(GEPoint3d<T>& p1, GEPoint3d<T>& p2)
//			{
//				
//			}
			
			T detectPositionWithLineValueXY ( GELine3d<T> line ) const
			{
				return this->Y*(line.end.X - line.start.X) 
								+ ( line.start.X - this->X)*line.end.Y 
								- line.start.Y*(line.end.X-this->X);
			}
			
			//TODO not so exact in case T == int 
			bool isInRayXY (GELine3d<T> line ) const
			{
				return this->detectPositionWithLineValueXY (line) == 0;
			}
			
			bool isAboveXY( GELine3d<T> line) 
			{
				return this->detectPositionWithLineValueXY (line) > 0;

			}
			
			bool isBelowXY( GELine3d<T> line) 
			{
				return this->detectPositionWithLineValueXY (line) < 0;
				
			}
			
			
			
#pragma mark -			
#pragma mark OPERATOR
			
			GEPoint3d<T> operator-() 
			{ 
				return GEPoint3d<T>(-this->X,-this->Y,-this->Z);
			}
			
			GEPoint3d<T> operator+ (const GEPoint3d<T>& other) 
			{ 
				return GEPoint3d<T>(this->X + other.X, this->Y + other.Y, this->Z + other.Z);
			}
			
			GEPoint3d<T> operator+ (const T val) 
			{ 
				return GEPoint3d<T>(this->X + val, this->Y + val, this->Z + val);
			}
			
			GEPoint3d<T> operator- (const GEPoint3d<T>& other) 
			{ 
				return GEPoint3d<T>(this->X - other.X, this->Y - other.Y, this->Z - other.Z);
			}
			
			GEPoint3d<T> operator- (const T val) 
			{ 
				return GEPoint3d<T>(this->X - val, this->Y - val, this->Z - val);
			}
			
			
			GEPoint3d<T> operator* (const GEPoint3d<T>& other) 
			{ 
				return GEPoint3d<T>(this->X * other.X, this->Y * other.Y, this->Z * other.Z);
			}
			
			GEPoint3d<T> operator* (const T val) 
			{ 
				return GEPoint3d<T>(this->X * val, this->Y * val, this->Z * val);
			}
			
			GEPoint3d<T> operator/ (const GEPoint3d<T>& other) 
			{ 
				return GEPoint3d<T>(this->X / other.X, this->Y / other.Y, this->Z / other.Z);
			}
			
			GEPoint3d<T> operator/ (const T val) 
			{ 
				return GEPoint3d<T>(this->X / val, this->Y / val, this->Z / val);
			}
			
			
		};
		
	}
}

#endif